<?php

/**
 * Create lookup table from base table
 * Lookup table is memory table with subset of data is select from base table
 * with lookup table, we can quick select from too complicated condition
 *
 */
class CLookupTable {
	/**
	 * @var CTable
	 */
	private $baseTable;
	private $baseTableName;
	private $baseCondition;
	private $baseConditionStr;
	private $memTableName;

	/**
	 * @var CTable
	 */
	private $memTable = null;

	/**
	 * @var CMySQLStore
	 */
	private $store;

	/**
	 * Constructor
	 *
	 * @param unknown_type $baseTableName
	 * @param unknown_type $baseCondition
	 */
	public function __construct($baseTableName, $baseCondition) {
		$this->baseTable = CTable($baseTableName);
		$this->baseTableName = $baseTableName;
		$this->baseCondition = $baseCondition;
		$this->memTableName = $this->buildMemTableName();
		$this->store = CStore::$default;
	}

	/**
	 * return list of cached table
	 *
	 * @return unknown
	 */
	public function getCachedTables() {
		$cacheName = 'cache_mysql_table_'.$this->baseTableName;
		if (!($tables=CSystem::$cachedata->get($cacheName))) {
			$this->store->connect();
			$rs = $this->store->query('show table status from `'.$this->store->database.'`
				where Name like "'.$this->baseTableName.'_%_cache"
				or Name="'.$this->baseTableName.'"', false);
			$tables = array();
			while ($row = mysql_fetch_assoc($rs)) {
				$tables[$row['Name']] = $row['Update_time'];
			}
			mysql_free_result($rs);
			CSystem::$cachedata->set($cacheName, $tables, 300);
		}

		$sourceTime = $tables[$this->baseTableName];
		if ($cacheTime = @$tables[$this->memTableName]) {
			if ($cacheTime < $sourceTime) unset($tables[$this->memTableName]);
		}

		return $tables;
	}

	/**
	 * Check whether if mem table exists, if not, create it
	 *
	 */
	public function checkExist() {
		if (null!==$this->memTable) return;
		/*
		$this->store->connect();
		$rs = $this->store->query('show tables like "'.$this->memTableName.'"');
		$tableExist = mysql_fetch_array($rs);
		mysql_free_result($rs);*/

		$tables = $this->getCachedTables();

		if (!isset($tables[$this->memTableName])) {
			$this->store->connect();
			$this->store->query('drop table if exists `'.$this->memTableName.'`', false);
			$this->store->query('create table `'.$this->memTableName.'` like `'.$this->baseTableName.'`', false);

			/*
			$alterCondition = '';
			$rs = $this->store->query('show keys from '.$this->memTableName);
			while ($key = mysql_fetch_assoc($rs)) {
				if ($key['Index_type']=='FULLTEXT') {
					$alterCondition .= ' drop key '.$key['Key_name'].', ';
				}
			}
			mysql_free_result($rs);

			$alterCondition .= ' engine=heap;';
			$this->store->query('alter table '.$this->memTableName.$alterCondition);
			*/

			//$selectCondtion = $this->store->condition_string($this->baseCondition);
			$this->store->query(
				'insert ignore into `'.$this->memTableName.
				'` select * from `'.$this->baseTableName.
				'` where '.$this->baseConditionStr, false);

			$this->memTable = CTable($this->memTableName)->master();
			$tables[$this->memTableName] = date('Y-m-d H:i:s');
			$cacheName = 'cache_mysql_table_'.$this->baseTableName;
			CSystem::$cachedata->set($cacheName, $tables, 300);
		} else {
			$this->memTable = CTable($this->memTableName);
		}
	}

	/**
	 * @return string Name of mem table
	 */
	public function buildMemTableName() {
		$this->baseConditionStr = $this->baseTable->store->condition_string($this->baseCondition);
		$code = crc32($this->baseConditionStr);
		$condition = preg_replace('@[^a-zA-Z0-9]@', '', $this->baseConditionStr);
		if (strlen($condition)>30) $condition = substr($condition, 0, 30);
		return $this->baseTableName.'_'.$condition.abs($code).'_cache';
	}

	public function count($condition, $options = array()) {
		$this->checkExist();
		return $this->memTable->count($condition, $options);
	}

	public function select($condition, $options = array()) {
		$this->checkExist();
		return $this->memTable->select($condition, $options);
	}

	public function &fields($fields) {
		$this->checkExist();
		return $this->memTable->fields($fields);
	}
}